package com.yonyou.pmclouds.trialinfo.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyou.iuap.tenant.entity.TenantInfo;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.condition.PublicDeployCondition;
import com.yonyou.pmclouds.basecom.conf.ProductActiveProperties;
import com.yonyou.pmclouds.basecom.conf.TrialInfoProperties;
import com.yonyou.pmclouds.basecom.entity.PageObject;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.exception.IllegalRequestArgException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.outter.tenant.TenantOperator;
import com.yonyou.pmclouds.outter.user.UserInfoQuery;
import com.yonyou.pmclouds.outter.user.UserOperator;
import com.yonyou.pmclouds.trialinfo.entity.TrialInfoVO;
import com.yonyou.pmclouds.trialinfo.rmiitf.TrialInfoMaintain;
import com.yonyou.pmclouds.trialinfo.rmiitf.TrialInfoQueryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.mail.internet.MimeMessage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Map;

import static com.yonyou.pmclouds.basecom.PMControllerConst.DEFAULT_PAGE_PAGE_START;
import static com.yonyou.pmclouds.basecom.PMControllerConst.DEFAULT_PAGE_SIZE;

@Slf4j
@Conditional(PublicDeployCondition.class)
@Controller
@RequestMapping(value = "/trialInfo")
public class TrialInfoController {

    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private TrialInfoMaintain trialInfoMaintain;
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private TrialInfoQueryService trialInfoQueryService;
    @Autowired
    private TrialInfoProperties trialInfoProperties;
    @Autowired
    private ProductActiveProperties activeProperties;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private UserInfoQuery userInfoQuery;
    @Autowired
    private UserOperator userOperator;
    @Autowired
    private TenantOperator tenantOperator;

    /**
     * 新增试用申请信息
     *
     * @param trialInfoVO
     * @return
     * @throws BusinessException
     */
    @ResponseBody
    @RequestMapping(value = "/insertTrialInfo")
    public Object insertTrialInfo(@RequestBody @Validated(TrialInfoVO.InsertValid.class) TrialInfoVO trialInfoVO, BindingResult errors) throws BusinessException {

        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }

        trialInfoVO = trialInfoMaintain.insertTrialInfoVO(trialInfoVO);
        sendEmailToAdmin(trialInfoVO);
        return trialInfoVO;
    }

    /**
     * 审批试用信息，新增企业账号，并开通应用试用
     *
     * @return
     * @throws BusinessException
     */
    @ResponseBody
    @RequestMapping(value = "/trialManage/approveTrialInfo")
    public Object approveTrialInfo(String pkTrialInfo) throws BusinessException {
        // 查询需要审批的试用申请信息
        TrialInfoVO trialInfoVO = trialInfoQueryService.queryTrialInfoById(pkTrialInfo);
        if (trialInfoVO == null)
            throw new BusinessException("未找到该信息");
        // 初始化租户信息
        String tenantId = addTenant(trialInfoVO);
        // 为租户绑定管理员
        String userId = addAdminToTenant(trialInfoVO, tenantId);
        // 试用开始时间、结束时间
        Date beginDate = new Date();
        Date endDate = getEndDate(beginDate);
        // 开通PMC试用
        tenantOperator.openPMCForTenant(tenantId, endDate);
        // 补全必要信息
        fillTrialInfo(trialInfoVO, tenantId, userId, beginDate, endDate);
        // 保存本地试用信息
        trialInfoVO = trialInfoMaintain.approveTrialInfoVO(trialInfoVO);
        // 发送邮件给联系人
        String mes = getEmailMessage(trialInfoVO, "receipt");
        sendEmail(mes, new String[]{trialInfoVO.getEmail()}, "友工程试用审批通过通知");
        return trialInfoVO;
    }

    /**
     * javaMail发送邮件
     *
     * @param message
     * @param tos
     * @throws BusinessException
     */
    private void sendEmail(String message, String[] tos, String subject) throws BusinessException {
        // 发送邮件给联系人

        MimeMessage mes = mailSender.createMimeMessage();

        MimeMessageHelper helper = null;
        try {
            helper = new MimeMessageHelper(mes, true, "utf-8");
            helper.setFrom("yygcy@yonyou.com");
            helper.setTo(tos);
            helper.setSubject(subject);
            helper.setText(message, true);

            mailSender.send(mes);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new BusinessException(e.getMessage());
        }
    }

    /**
     * 获得图片信息
     *
     * @return
     */
    /*private  String getImageBinary()  {
        String email_image_path = trialInfoProperties.getTrial_approve_success().get("email_image_path");
        String email_image_type = trialInfoProperties.getTrial_approve_success().get("email_image_type");

        InputStream stream = getClass().getClassLoader().getResourceAsStream(email_image_path);

        BASE64Encoder encoder = new sun.misc.BASE64Encoder();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        BufferedImage bi = null;
        try {
            bi = ImageIO.read(stream);
            baos = new ByteArrayOutputStream();
            ImageIO.write(bi, email_image_type, baos);
            byte[] bytes = baos.toByteArray();

            return encoder.encodeBuffer(bytes).trim();
        } catch (IOException e) {
            log.error("读取文件信息失败，具体信息为："+e.getMessage());
        }finally {
            try {
                baos.close();
            } catch (IOException e) {
                log.error("关闭流失败，具体信息为："+e.getMessage());
            }
        }
        return null;
    }*/
    @ResponseBody
    @RequestMapping(value = "/trialManage/queryTrialInfoById")
    public Object queryTrialInfoById(String pkTrialInfo) {
        TrialInfoVO trialInfoVO = trialInfoQueryService.queryTrialInfoById(pkTrialInfo);
        return trialInfoVO;
    }

    @GetMapping(value = "/trialManage/queryTrialInfoList")
    @ResponseBody
    public PageObject<TrialInfoVO> queryTrialInfoList(@RequestParam(name = "state", required = false) String state,
                                                      @RequestParam(name = "pageStart", required = false, defaultValue = DEFAULT_PAGE_PAGE_START) String pageStart,
                                                      @RequestParam(name = "pageSize", required = false, defaultValue = DEFAULT_PAGE_SIZE) String pageSize)
            throws BusinessException {
        Byte billstatus = state == null ? null : Byte.parseByte(state);
        PageObject<TrialInfoVO> trialPage = trialInfoQueryService.queryTrialInfoList(
                billstatus, Integer.valueOf(pageStart), Integer.valueOf(pageSize));
        return trialPage;
    }

    /**
     * 发送申请邮件给管理员
     */
    private void sendEmailToAdmin(TrialInfoVO trialInfoVO) throws BusinessException {

        String message = getEmailMessage(trialInfoVO, "approve");

        String[] adminEmails = trialInfoProperties.getAdmin_email();

        sendEmail(message, adminEmails, "友工程试用申请");
    }

    /**
     * 得到邮件内容，并替换显示字段
     *
     * @param trialInfoVO
     * @return
     */
    private String getEmailMessage(TrialInfoVO trialInfoVO, String sign) {
        String emailFilePath = "";
        if ("approve".equals(sign)) {
            emailFilePath = trialInfoProperties.getMessage_path();
        } else if ("receipt".equals(sign)) {
            emailFilePath = trialInfoProperties.getReceiptmessage_path();
        }


        String message = getEmailFromResource(emailFilePath);

        if ("approve".equals(sign)) {
            message = buildApproveEmailMessage(trialInfoVO, message);
        } else if ("receipt".equals(sign)) {
            message = buildReceiptEmailMessage(message);
        }


        return message;
    }

    /**
     * 从静态资源文件中获取邮件内容
     *
     * @return
     */
    private String getEmailFromResource(String filePath) {

        StringBuffer messageBuffer = new StringBuffer();

        InputStreamReader stream = null;
        try {
            stream = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(filePath), "utf-8");
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage());
        }

        BufferedReader br = null;
        try {
            br = new BufferedReader(stream);
            String line = null;
            while ((line = br.readLine()) != null) {
                messageBuffer.append(line);
            }
        } catch (Exception e) {
            log.error("读取文件信息失败，具体信息为：" + e.getMessage());
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    log.error("关闭文件流失败，具体信息为：" + e.getMessage());
                }
            }
        }

        return messageBuffer.toString();
    }

    /**
     * 对邮件中需要显示的内容进行替换
     *
     * @param trialInfoVO
     * @param message
     * @return
     */
    private String buildApproveEmailMessage(TrialInfoVO trialInfoVO, String message) {

        if (trialInfoVO == null || message == null)
            return null;

        String province = trialInfoVO.getProvince() == null ? "" : trialInfoVO.getProvince();
        String city = trialInfoVO.getCity() == null ? "" : trialInfoVO.getCity();
        String county = trialInfoVO.getCounty() == null ? "" : trialInfoVO.getCounty();
        String address = trialInfoVO.getDetailaddress() == null ? "" : trialInfoVO.getDetailaddress();

        String enterAddress = province + city + county + address;

        message = message.replace("${tenantname}", trialInfoVO.getTenantname());
        message = message.replace("${enterAddress}", enterAddress);
        message = message.replace("${linkman}", trialInfoVO.getLinkman());
        message = message.replace("${mobilephone}", trialInfoVO.getMobilephone());
        message = message.replace("${email}", trialInfoVO.getEmail());
        message = message.replace("${approvelink}", trialInfoProperties.getApprove_hyperlink() + "?pkTrialInfo=" + trialInfoVO.getPkTrialInfo());
        message = message.replace("${pkTrialInfo}", trialInfoVO.getPkTrialInfo());
        return message;
    }

    /**
     * 对邮件中需要显示的内容进行替换
     *
     * @param message
     * @return
     */
    private String buildReceiptEmailMessage(String message) {

        message = message.replace("${receipt_imglink}", trialInfoProperties.getReceipt_imglink());
        message = message.replace("${center_hyperlink}", trialInfoProperties.getCenter_hyperlink());
        message = message.replace("${pmc_hyperlink}", trialInfoProperties.getPmc_hyperlink());

        return message;
    }

    /**
     * 补全申请信息中的数据
     * <p>
     * 时间信息都在controller中可以获取到，
     * 因此业务信息的填写放到这里较为方便
     *
     * @param trialInfoVO
     * @param tenantId
     * @param beginDate
     * @param endDate
     */
    private void fillTrialInfo(TrialInfoVO trialInfoVO, String tenantId, String userId, Date beginDate, Date endDate) {
        trialInfoVO.setPkTenant(tenantId);
        trialInfoVO.setUserid(userId);
        trialInfoVO.setApprovetime(beginDate);
        trialInfoVO.setEndtime(endDate);
        trialInfoVO.setApprover(RuntimeEnvironment.getLoginUserId());
        trialInfoVO.setBillstatus((byte) 2);

        trialInfoVO.setAccountQuantity(trialInfoProperties.getAccount_quantity());

        int periodDays = trialInfoProperties.getPeriod() == null ? 0 : Integer.valueOf(trialInfoProperties.getPeriod());
        int lease = periodDays / 30;

        trialInfoVO.setLease(lease);
        trialInfoVO.setProductId(activeProperties.getAppBuziId());

    }

    /**
     * 获取到期时间
     *
     * @param beginDate
     * @return
     */
    private Date getEndDate(Date beginDate) {
        int periodDays = 0;
        if (trialInfoProperties.getPeriod() != null && !"".equals(trialInfoProperties.getPeriod())) {
            periodDays = Integer.valueOf(trialInfoProperties.getPeriod());
        }

        Long period = periodDays * 24 * 60 * 60 * 1000L;
        // 试用截止时间
        return new Date(beginDate.getTime() + period);
    }


    /**
     * 为租户添加管理员
     *
     * @param trialInfoVO
     * @param tenantId
     */
    private String addAdminToTenant(TrialInfoVO trialInfoVO, String tenantId) throws BusinessException {
        return tenantOperator.addAdminToTenant(trialInfoVO.getLinkman(), trialInfoVO.getMobilephone(), trialInfoVO.getEmail(), tenantId);
    }


    /**
     * 新增企业账号
     *
     * @param trialInfoVO
     * @return
     * @throws BusinessException
     */
    private String addTenant(TrialInfoVO trialInfoVO) throws BusinessException {

        TenantInfo tenantInfo = new TenantInfo();
        tenantInfo.setTenantName(trialInfoVO.getTenantname());
        tenantInfo.setTenantFullName(trialInfoVO.getTenantname());
        tenantInfo.setUserName(trialInfoVO.getLinkman());
        tenantInfo.setUserEmail(trialInfoVO.getEmail());
        tenantInfo.setUserMobile(trialInfoVO.getMobilephone());
        tenantInfo.setSystemCode(ApplicationConsts.APPLICATION_ID);
        tenantInfo.setSendMessage("send");
        tenantInfo.setPassword("");

        Map addResultMap = tenantOperator.addTenant(tenantInfo);

        if (addResultMap == null || addResultMap.size() == 0)
            return null;

        return addResultMap.get("tenant") == null ? null : (String) (((Map) addResultMap.get("tenant")).get("tenantId"));

    }


}
